﻿using System;
using System.Collections.Generic;
using System.Text;
using Castle.ActiveRecord.Queries;
using log4net;
using Pampa.CRUD.Core;
using Pampa.Grid.Core.Filters;

namespace Pampa.Grid.Data
{
    public class HqlQueryBuilder : AbstractQueryBuilder
    {
        protected IList<string> joinSources;

        public HqlQueryBuilder()
        {
            joinSources = new List<string>();
        }

        public SimpleQuery<T> GetSelectQuery<T>(Type entityType)
        {
            string query = this.GetQueryString(null);
            SimpleQuery<T> entitiesQuery = new SimpleQuery<T>(entityType, query);

            foreach (KeyValuePair<string, object> parameter in parameters)
            {
                entitiesQuery.SetParameter(parameter.Key.Replace(":", ""), parameter.Value);
            }

            logger.Debug("query: " + entitiesQuery.Query);

            return entitiesQuery;
        }

        public ScalarQuery<long> GetCountQuery(Type entityType)
        {
            string query = this.GetCountQueryString();
            ScalarQuery<long> countQuery = new ScalarQuery<long>(entityType, query);

            foreach (KeyValuePair<string, object> parameter in parameters)
            {
                countQuery.SetParameter(parameter.Key.Replace(":", ""), parameter.Value);
            }

            return countQuery;
        }

        protected override string GetParameterWithMark(string paramName)
        {
            return ":" + paramName;
        }

        protected override string GetSelectClause(int? top)
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine(top.HasValue ? " TOP " + top.Value.ToString() : "");
            sb.AppendLine(" " + GetAlias(this.Source) + " ");

            return sb.ToString();
        }

        protected override string GetScript(GroupFilter filter)
        {
            if (!string.IsNullOrEmpty(filter.Join))
            {
                if (!joinSources.Contains(filter.Join))
                {
                    string join = ((filter.Parent is OrGroupFilter) ? " left " : "") + " join " + GetAlias(Source);
                    AddJoin(join + "." + filter.Join + " as " + GetAlias(filter.Join) + " ");
                    joinSources.Add(filter.Join);
                }
            }

            return base.GetScript(filter);
        }

        protected override string GetScript(SimpleFilter filter)
        {
            string paramName = GetParameterWithMark(GetParameterName(filter.Field));

            string comp = filter.OperationScript;
            object value = filter.ValueScript;

            parameters.Add(paramName, value);

            if (string.IsNullOrEmpty(filter.Source))
                return "(" + GetAlias(Source) + "." + filter.Field + " " + comp + " " + paramName + ")";
            else if (filter.Field == "$identity")
                return "(" + GetAlias(filter.Source) + " " + comp + " " + paramName + ")";
            else
                return "(" + GetAlias(filter.Source) + "." + filter.Field + " " + comp + " " + paramName + ")";
        }
    }
}
